package com.hbu.product.hbumallproduct.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbu.common.utils.PageUtils;
import com.hbu.common.utils.Query;
import com.hbu.product.hbumallproduct.dao.AttrAttrgroupRelationDao;
import com.hbu.product.hbumallproduct.dao.AttrDao;
import com.hbu.product.hbumallproduct.dao.AttrGroupDao;
import com.hbu.product.hbumallproduct.dao.CategoryDao;
import com.hbu.product.hbumallproduct.entity.AttrAttrgroupRelationEntity;
import com.hbu.product.hbumallproduct.entity.AttrEntity;
import com.hbu.product.hbumallproduct.entity.AttrGroupEntity;
import com.hbu.product.hbumallproduct.entity.CategoryEntity;
import com.hbu.product.hbumallproduct.service.AttrService;
import com.hbu.product.hbumallproduct.service.CategoryService;
import com.hbu.product.hbumallproduct.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.hbu.common.utils.Constant.GET_ALL_DATA;
import static com.hbu.common.utils.Constant.KEY;
import static com.hbu.product.hbumallproduct.utils.Constant.BASE_ATTR_TYPE;


/**
 * @author 90458
 */
@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    private AttrAttrgroupRelationDao attrAttrgroupRelationDao;

    private CategoryDao categoryDao;

    private AttrGroupDao attrGroupDao;

    private CategoryService categoryService;

    private HashMap<String, Integer> attrTypeMap = new HashMap<>(2);

    private final static String ATTR_TYPE_BASE = "base";

    private final static String ATTR_TYPE_SALE = "sale";

    public AttrServiceImpl(AttrAttrgroupRelationDao attrAttrgroupRelationDao, CategoryDao categoryDao, AttrGroupDao attrGroupDao, CategoryService categoryService) {
        this.attrAttrgroupRelationDao = attrAttrgroupRelationDao;
        this.categoryDao = categoryDao;
        this.attrGroupDao = attrGroupDao;
        this.categoryService = categoryService;
    }

    @PostConstruct
    public void initAttrTypeMap() {
        attrTypeMap.put("sale", 0);
        attrTypeMap.put("base", 1);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAttr(AttrVO attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtil.copyProperties(attr, attrEntity);
        this.save(attrEntity);
        if (BASE_ATTR_TYPE.equals(attr.getAttrType()) && attr.getAttrGroupId() != null) {
            attr.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationDao.insert(new AttrAttrgroupRelationEntity(attr));
        }
    }

    @Override
    public PageUtils getAttrList(Map<String, Object> params, Long catelogId, String attrType) {
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().eq("attr_type", attrTypeMap.get(attrType));
        if (!GET_ALL_DATA.equals(catelogId)) {
            queryWrapper.eq("catelog_id", catelogId);
        }
        String key = (String) params.get(KEY);
        if (StringUtils.hasText(key)) {
            queryWrapper.and(obj -> obj.eq("attr_id", key).or().like("attr_name", key));
        }
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), queryWrapper);
        PageUtils pageUtils = new PageUtils(page);
        List<AttrResponseVO> results = page.getRecords().stream().map(attr -> {
            AttrResponseVO attrResponseVO = new AttrResponseVO(attr);
            // 获取attrGroupName,有且仅有base，即基本属性有属性分组的概念
            if (ATTR_TYPE_BASE.equals(attrType)) {
                Optional<AttrAttrgroupRelationEntity> attrAttrgroupRelationEntityOptional = Optional.ofNullable(attrAttrgroupRelationDao
                        .selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId())));
                attrAttrgroupRelationEntityOptional.flatMap(attrAttrgroupRelationEntity ->
                                Optional.ofNullable(attrGroupDao.selectById(attrAttrgroupRelationEntity.getAttrGroupId())))
                        .ifPresent(attrGroupEntity -> attrResponseVO.setGroupName(attrGroupEntity.getAttrGroupName()));
            }
            // 获取catalogName
            CategoryEntity category = categoryDao.selectById(attr.getCatelogId());
            attrResponseVO.setCatelogName(category.getName());
            return attrResponseVO;
        }).collect(Collectors.toList());
        pageUtils.setList(results);
        return pageUtils;
    }

    @Override
    public AttrInfoVO getInfoById(Long attrId) {
        AttrInfoVO attrInfoVo = new AttrInfoVO();
        AttrEntity attrEntity = getById(attrId);
        BeanUtil.copyProperties(attrEntity, attrInfoVo);
        Optional<AttrAttrgroupRelationEntity> attrAttrGroupRelationOptional
                = Optional.ofNullable(attrAttrgroupRelationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId())));
        attrAttrGroupRelationOptional.ifPresent(attrAttrGroupRelation -> {
            attrInfoVo.setAttrGroupId(attrAttrGroupRelation.getAttrGroupId());
            Optional<AttrGroupEntity> attrGroupEntityOptional = Optional.ofNullable(attrGroupDao.selectById(attrAttrGroupRelation.getAttrGroupId()));
            attrGroupEntityOptional.ifPresent(attrGroupEntity -> attrInfoVo.setAttrGroupName(attrGroupEntity.getAttrGroupName()));
        });
        attrInfoVo.setCatelogPath(categoryService.findCategoryPath(attrEntity.getCatelogId()));
        return attrInfoVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cascadeUpdate(AttrUpdateVO attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtil.copyProperties(attr, attrEntity);
        this.baseMapper.updateById(attrEntity);
        // 销售属性是没有分组的
        if (BASE_ATTR_TYPE.equals(attr.getAttrType())) {
            // 更新属性分组之前，要看之前有没有分组
            Long count = attrAttrgroupRelationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            if (count > 0) {
                // 大于0，说明该属性存在分组，直接进行更新
                attrAttrgroupRelationDao.updateAttrGroupIdByAttrId(attr.getAttrId(), attr.getAttrGroupId());
            } else {
                // 否则，就要进行插入操作
                AttrAttrgroupRelationEntity attrAttrgroupRelation = new AttrAttrgroupRelationEntity();
                attrAttrgroupRelation.setAttrId(attr.getAttrId());
                attrAttrgroupRelation.setAttrGroupId(attr.getAttrGroupId());
                Optional.ofNullable(attrGroupDao.selectById(attr.getAttrGroupId()))
                        .ifPresent(attrGroupEntity -> attrAttrgroupRelation.setAttrSort(attrGroupEntity.getSort()));
                attrAttrgroupRelationDao.insert(attrAttrgroupRelation);
            }
        }

    }

    @Override
    public List<AttrRelationVO> getAttrRelation(Long attrGroupId) {
        List<AttrAttrgroupRelationEntity> relationEntities = attrAttrgroupRelationDao.
                selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrGroupId));
        List<AttrRelationVO> collect = null;
        if (ArrayUtil.isNotEmpty(relationEntities)) {
            collect = relationEntities.stream().map(relationEntity -> {
                AttrEntity attrEntity = this.baseMapper.selectById(relationEntity.getAttrId());
                return new AttrRelationVO(attrEntity);
            }).collect(Collectors.toList());
        }
        return collect;
    }

    @Override
    public PageUtils getNoAttrRelation(Map<String, Object> params, Long attrGroupId) {
        // 根据传入的属性分组ID，查出对应的catelogId
        Long catelogId = attrGroupDao.getCatelogIdByAttrGroupId(attrGroupId);
        List<Long> attrIds = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>()
                .eq("catelog_id",catelogId)).stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>()
                .eq("catelog_id", catelogId)
                .eq("attr_type", attrTypeMap.get(ATTR_TYPE_BASE));
        if (ArrayUtil.isNotEmpty(attrIds)) {
            queryWrapper.notIn("attr_id", attrIds);
        }
        String key = (String) params.get(KEY);
        if (StringUtils.hasText(key)) {
            queryWrapper.and(record -> record.eq("attr_id", key).or().like("attr_name", key));
        }
        return new PageUtils(this.page(new Query<AttrEntity>().getPage(params), queryWrapper));
    }

}